#pragma once
#include <pthread.h>
#include <unistd.h>
#include <string>
#include <vector>
#include <queue>
#define NUM 5
using namespace std;
namespace yui
{
    template <class T>
    class PthreadPool
    {
    public:
        PthreadPool(int num = NUM) : _num(num)
        {
            // 初始化
            pthread_mutex_init(&_mutex, nullptr);
            pthread_cond_init(&_cond, nullptr);
        }
        ~PthreadPool()
        {
            // 销毁
            pthread_mutex_destroy(&_mutex);
            pthread_cond_destroy(&_cond);
        }
        void init()
        {
            // 创建一批线程
            for (int i = 0; i < _num; ++i)
            {
                pthread_t *pth = new pthread_t;
                _threads.push_back(*pth);
            }
        }
        void start()
        {
            for (int i = 0; i < _num; ++i)
            {
                pthread_create(&_threads[i], nullptr, threadRun, this);
            }
        }
        static void *threadRun(void *arg)
        {
            pthread_detach(pthread_self()); // 避免线程等待。
            auto p = static_cast<PthreadPool<T>*>(arg);
            
            while (true)
            {
                // 加锁，访问公共资源
                pthread_mutex_lock(&p->_mutex);
                while (p->_tasks.empty())
                {
                    // 如果任务队列为空，开始等待
                    pthread_cond_wait(&p->_cond, &p->_mutex);
                }
                // 开始执行任务
                T tmp = p->_tasks.front();
                p->_tasks.pop();
                // 处理任务
                cout << "获取任务：" << tmp << endl;
                //...
                // 解锁
                pthread_mutex_unlock(&p->_mutex);
            }
        }
        void pushTask(T &task)
        {
            // 加锁
            pthread_mutex_lock(&_mutex);
            _tasks.push(task);
            // 唤醒线程处理
            pthread_cond_signal(&_cond);
            pthread_mutex_unlock(&_mutex);
        }

    private:
        vector<pthread_t> _threads; // 线程容器
        queue<T> _tasks;            // 任务队列
        int _num;                   // 线程池中的线程数量
        pthread_mutex_t _mutex;     // 互斥锁
        pthread_cond_t _cond;       // 条件变量
    };

}